#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>


class TcpClient{
  private:
    std::string svr_ip;
    int svr_port;
    int sock;
  public:
    TcpClient(std::string _ip,int _port):svr_ip(_ip),svr_port(_port),sock(-1)
    {}

    //初始化客户端
    void InitTcpClient()
    {
      sock = socket(AF_INET,SOCK_STREAM,0);
      if(sock < 0){
        std::cerr << "socket error" << std::endl;
        exit(2);
      }

    }
    
    //启动客户端，连接服务器
    void Start()
    {
      struct sockaddr_in peer;
      memset(&peer,0,sizeof(peer));
      peer.sin_family = AF_INET;
      peer.sin_port = htons(svr_port);
      peer.sin_addr.s_addr = inet_addr(svr_ip.c_str());//点分式IP转化为整型式,因为要求C语言风格的字符串，所以将C++风格转化成C语言风格

      if(connect(sock,(struct sockaddr*)&peer,sizeof(peer)) == 0){
        //success
        std::cout << "connect success..." << std::endl;
        Request(sock);//连接成功，开始请求服务
      }
      else{
        //false
        std::cout << "connect failed..." << std::endl;
      }
    }

    //往服务器发消息
    void Request(int sock)
    {
      std::string message;
      char buffer[128];
      while(true){
        std::cout << "Please Enter# ";
        std::cin >> message;
        //将message的信息往sock里写，因为message是C++的string类型，而write需要的是C语言的字符串，所以需要先转换为C语言风格，sock的本质就是文件描述符
        write(sock,message.c_str(),message.size());

        ssize_t s = read(sock,buffer,sizeof(buffer)-1);
        if(s > 0) buffer[s] = 0;

        std::cout << "server echo# " << buffer << std::endl;
      }
    }

    ~TcpClient()
    {
      if(sock >= 0)
        close(sock);
    }
};
